package mylibrary.security.UDPChat;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.text.DefaultCaret;

public class MainFrame extends JFrame implements Runnable {

	private static final String CHARSET = "utf-8";
	private UDPSocket socket;
	private InitDialog initDialog;
	public static final int DEFAULT_WIDTH = 500;
	public static final int DEFAULT_HEIGHT = 400;
	
	private JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
	private JTextArea sendTextArea = new JTextArea();
	private JTextArea receiveTextArea = new JTextArea();
	private JPanel buttonPanel = new JPanel();
	
	public MainFrame() {
		this.initDialog = new InitDialog(this);
		if(initDialog.isCancelled()) {
			System.exit(0);
		} else {
			initSocket();
			initGUI();
		}
	}
	
	public void initSocket() {
		try {
			socket = new UDPSocket(initDialog.getLocalHost(), initDialog.getRemoteHost(), initDialog.getReceivePort(), initDialog.getSendPort());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void initGUI() {
		setTitle("From: " + initDialog.getLocalHost() + " To: " + initDialog.getRemoteHost());
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setMinimumSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
		this.getContentPane().add(splitPane, BorderLayout.CENTER);
		this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
		initReceivePanel();
		initSendPanel();
		initButtonPanel();
		
		this.setLocationRelativeTo(null);
		this.setVisible(true);
		this.setResizable(false);
	}
	
	private void initButtonPanel() {
		JButton sendButton = new JButton("Send");
		sendButton.setMnemonic(KeyEvent.VK_S);
		sendButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				try {
					send(sendTextArea.getText());
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		});
		
		JButton exitButton = new JButton("Close");
		exitButton.setMnemonic(KeyEvent.VK_X);
		exitButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				socket.close();
				System.exit(0);
			}
		});
		buttonPanel.setBorder(BorderFactory.createEtchedBorder());
		buttonPanel.add(sendButton);
		buttonPanel.add(exitButton);
	}
	
	private void initReceivePanel() {
		receiveTextArea.setEditable(false);
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		panel.setBorder(BorderFactory.createEtchedBorder());
		JLabel label = new JLabel();
		label.setText("Received message:");
		panel.add(label, BorderLayout.NORTH);
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.getViewport().add(receiveTextArea);
		DefaultCaret caret = (DefaultCaret) receiveTextArea.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		panel.add(scrollPane, BorderLayout.CENTER);
		panel.setMinimumSize(new Dimension(0, DEFAULT_WIDTH/3));
		splitPane.add(panel);
	}
	
	private void initSendPanel() {
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		panel.setBorder(BorderFactory.createEtchedBorder());
		JLabel label = new JLabel();
		label.setText("To be sent message:");
		panel.add(label, BorderLayout.NORTH);
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setWheelScrollingEnabled(true);
		DefaultCaret caret = (DefaultCaret) sendTextArea.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		sendTextArea.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent event) {
				if((event.getKeyCode() == KeyEvent.VK_ENTER) && event.isControlDown()) {
					try {
						send(sendTextArea.getText());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		scrollPane.getViewport().add(sendTextArea);
		panel.add(scrollPane, BorderLayout.CENTER);
		splitPane.add(panel);
	}
	
	public void receive() throws Exception {
		String message = new String(socket.receive(), CHARSET);
		StringBuilder sb = new StringBuilder();
		sb.append(receiveTextArea.getText());
		sb.append(message);
		receiveTextArea.setText(sb.toString());
	}
	
	public void send(String message) throws Exception {
		if(message.isEmpty()) {
			return;
		}
		
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		StringBuilder sendMessage = new StringBuilder();
		sendMessage.append(df.format(new Date()));
		sendMessage.append(" (" + initDialog.getUserName() + ") ");
		sendMessage.append("\r\n");
		sendMessage.append(message);
		sendMessage.append("\r\n");
		message = sendMessage.toString();
		socket.send(message.getBytes(CHARSET));
		StringBuilder receiveMessage = new StringBuilder(receiveTextArea.getText());
		receiveMessage.append(sendMessage);
		receiveTextArea.setText(receiveMessage.toString());
		sendTextArea.setText(null);
	}
	
	public void run() {
		while(true) {
			try {
				receive();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		MainFrame frame = new MainFrame();
		Thread t = new Thread(frame);
		t.start();
	}
}
